import {
  useRef,
  useState,
  forwardRef,
  useImperativeHandle,
  useMemo,
} from 'react'
import {
  StyleSheet,
  View,
  Animated,
  Pressable,
  LayoutChangeEvent,
  ViewStyle,
  TextStyle,
  ScrollView,
} from 'react-native'
import { common } from '../../assets/style/common'
type TabMenusProp = {
  list: any[]
  initActive: number
  onChange?: (index: number) => void
  style?: ViewStyle
  textStyle?: TextStyle
  isScroll?: boolean // 是否可以左右滚动 默认是
  disabled?: boolean
}
export default forwardRef(function (props: TabMenusProp, ref) {
  const { initActive: initActive = 0 } = props
  const lineX = useRef(new Animated.Value(0)).current
  const [containWidth, setContainWidth] = useState(0)
  const [menus, setMenu] = useState<any[]>(
    props.list.map((item, i) =>
      Object.assign(
        { active: i === initActive, lineX: 0, x: 0, width: 0, key: i },
        wrapItem(item),
      ),
    ),
  )
  const isScroll = typeof props.isScroll === 'undefined' ? true : props.isScroll
  const scrollViewRef = useRef<ScrollView>(null)
  const scrollPosX = useMemo(() => {
    return menus.map(item => {
      const { x, width } = item
      const ret = { key: item.key, x: x }
      if (!x || !containWidth) return ret
      ret.x = x + (width - containWidth) / 2
      return ret
    })
  }, [containWidth, menus])

  const [lineOpacity, setLineOpacity] = useState(false)
  function wrapItem(item: any) {
    return typeof item === 'object' && !(item instanceof Array)
      ? item
      : { label: item }
  }
  function onMenusLayout(e: LayoutChangeEvent, index: number) {
    let { x, width } = e.nativeEvent.layout
    const lineX2 = x + (width - 32) / 2
    const newMenus = menus.map((item, key) => {
      return key === index
        ? Object.assign({}, wrapItem(item), { lineX: lineX2, x, width })
        : item
    })
    setMenu(newMenus)
  }

  function onContainLayout(e: LayoutChangeEvent) {
    setContainWidth(e.nativeEvent.layout.width)
    startAnimated(menus, false)
    setTimeout(() => {
      setLineOpacity(true)
    }, 250)
  }
  // 给线做动画
  function startAnimated(menuList: any[], animated = true) {
    const index = menuList.findIndex(item => item.active)
    isScroll &&
      scrollViewRef.current?.scrollTo({ x: scrollPosX[index].x, animated })
    Animated.timing(lineX, {
      toValue: menuList[index].lineX,
      useNativeDriver: true,
      duration: animated ? 300 : 0,
    }).start()
  }

  useImperativeHandle(
    ref,
    () => ({
      changeByIndex(index: number) {
        setMenu(menu => {
          const newMenu = menu.map((item, i) =>
            Object.assign(item, {
              active: index === i,
            }),
          )
          startAnimated(newMenu)
          return newMenu
        })
      },
    }),
    [scrollPosX],
  )

  return (
    <TabMenusWrap
      onContainLayout={onContainLayout}
      style={props.style}
      scrollViewRef={scrollViewRef}
      isScroll={isScroll}
    >
      <View style={[styles.mainMenuWrap, common.flexCol]}>
        {menus.map((item, index) => {
          // eslint-disable-next-line react-hooks/rules-of-hooks
          const color = useRef(
            new Animated.Value(initActive === index ? 1 : 0),
          ).current // 给文字颜色做动画
          if (item && item.active) {
            Animated.timing(color, {
              toValue: 1,
              useNativeDriver: false,
              duration: 300,
            }).start()
          } else {
            Animated.timing(color, {
              toValue: 0,
              useNativeDriver: false,
              duration: 300,
            }).start()
          }
          function onMenusClick() {
            console.log(props.disabled, 'props.disabled')
            if (props.disabled) return
            const newMenus = menus.map((menu, key) => {
              return Object.assign({}, wrapItem(menu), {
                active: key === index,
              })
            }) // 新创建menus的值
            setMenu(newMenus)
            startAnimated(newMenus)
            props.onChange && props.onChange(index)
          }

          return (
            <Pressable
              style={[common.flexCol, styles.menuItem]}
              key={item.key}
              onLayout={e => onMenusLayout(e, index)}
              onPress={onMenusClick}
            >
              <Animated.Text
                style={[
                  styles.menusLabel,
                  props.textStyle,
                  {
                    color: color.interpolate({
                      inputRange: [0, 1],
                      outputRange: [
                        'rgba(255,255,255,1)',
                        'rgba(254,214,111,1)',
                      ],
                    }),
                    transform: [
                      {
                        scale: color.interpolate({
                          inputRange: [0, 1],
                          outputRange: [1, 1.1],
                        }),
                      },
                    ],
                  },
                ]}
              >
                {item.label}
              </Animated.Text>
            </Pressable>
          )
        })}
        <View style={[styles.menusWrap, { opacity: +lineOpacity }]}>
          <Animated.View
            style={[
              styles.menusLine,
              {
                transform: [{ translateX: lineX }],
              },
            ]}
          />
        </View>
      </View>
    </TabMenusWrap>
  )
})
interface TabMenusWrap {
  isScroll: boolean
  scrollViewRef: any
  children: any
  onContainLayout: any
  style?: ViewStyle
}
function TabMenusWrap(props: TabMenusWrap) {
  return props.isScroll ? (
    <ScrollView
      horizontal
      showsHorizontalScrollIndicator={false}
      style={[styles.mainMenu, props.style]}
      ref={props.scrollViewRef}
      onLayout={props.onContainLayout}
    >
      {props.children}
    </ScrollView>
  ) : (
    <View
      style={[styles.mainMenu, props.style]}
      onLayout={props.onContainLayout}
    >
      {props.children}
    </View>
  )
}
const styles = StyleSheet.create({
  mainMenu: {
    height: 32,
    width: '100%',
    paddingVertical: 8,
    paddingTop: 2,
  },
  mainMenuWrap: {
    justifyContent: 'space-evenly',
    flexWrap: 'wrap',
    width: '100%',
  },
  menuItem: {
    paddingHorizontal: 24,
    flexDirection: 'column',
    justifyContent: 'center',
    alignItems: 'center',
    paddingTop: 6,
  },
  menusLabel: {
    color: '#fff',
    textAlign: 'center',
    fontSize: 14,
  },
  menusLine: {
    height: 3,
    width: 32,
    backgroundColor: '#fed66f',
    borderRadius: 3,
  },
  menusWrap: {
    height: 3,
    width: '100%',
    marginTop: 8,
  },
})

export type TabMenusType = {
  changeByIndex: (index: number) => void
}
